/**
 * 
 */
package gates;

import gates.internals.NBaseTransistor;

/**
 * @author denis
 * 
 */
public class Xor extends Gate {
	static {
		filename = "simple_xor.properties";
	}

	public Xor(int defect) {
		this(false, false, defect);
	}

	public Xor(boolean in_1, boolean in_2, int defect) {
		this(new GateInput(in_1), new GateInput(in_2), defect);
	}

	public Xor(GateInput in_1, GateInput in_2, int defect) {
		super(in_1, in_2, defect);
	}

	protected void generateCircuit() {
		// not gate: sencond_input
		NBaseTransistor nbTransNot_2ndInput = new NBaseTransistor();
		bat.addObserver(nbTransNot_2ndInput.getCollector());
		input_2.addObserver(nbTransNot_2ndInput.getBase());
		
		// and gate: first_input + not_output

		NBaseTransistor nbTrans1_1stAnd = new NBaseTransistor();
		bat.addObserver(nbTrans1_1stAnd.getCollector());
		input_1.addObserver(nbTrans1_1stAnd.getBase());

		NBaseTransistor nbTrans2_1stAnd = new NBaseTransistor();
		bat.addObserver(nbTrans2_1stAnd.getCollector());
		nbTransNot_2ndInput.getEmitter().addObserver(nbTrans2_1stAnd.getBase());

		NBaseTransistor nbTrans3_1stAnd = new NBaseTransistor();
		bat.addObserver(nbTrans3_1stAnd.getCollector());
		nbTrans1_1stAnd.getEmitter().addObserver(nbTrans3_1stAnd.getBase());
		nbTrans2_1stAnd.getEmitter().addObserver(nbTrans3_1stAnd.getBase());
		
		// not gate: first_input

		NBaseTransistor nbTransNot_1stInput = new NBaseTransistor();
		bat.addObserver(nbTransNot_1stInput.getCollector());
		input_1.addObserver(nbTransNot_1stInput.getBase());
		
		// and gate: not_output + second_input

		NBaseTransistor nbTrans1_2ndAnd = new NBaseTransistor();
		bat.addObserver(nbTrans1_2ndAnd.getCollector());
		nbTransNot_1stInput.getEmitter().addObserver(nbTrans1_2ndAnd.getBase());

		NBaseTransistor nbTrans2_2ndAnd = new NBaseTransistor();
		bat.addObserver(nbTrans2_2ndAnd.getCollector());
		input_2.addObserver(nbTrans2_2ndAnd.getBase());

		NBaseTransistor nbTrans3_2ndAnd = new NBaseTransistor();
		bat.addObserver(nbTrans3_2ndAnd.getCollector());
		nbTrans1_2ndAnd.getEmitter().addObserver(nbTrans3_2ndAnd.getBase());
		nbTrans2_2ndAnd.getEmitter().addObserver(nbTrans3_2ndAnd.getBase());
		
		// or gate: first_and_output + second_and_output
		
		NBaseTransistor nbTrans1_Or = new NBaseTransistor();
		bat.addObserver(nbTrans1_Or.getCollector());
		nbTrans3_1stAnd.getEmitter().addObserver(nbTrans1_Or.getBase());

		NBaseTransistor nbTrans2_Or = new NBaseTransistor();
		nbTrans1_Or.getEmitter().addObserver(nbTrans2_Or.getCollector());
		nbTrans3_2ndAnd.getEmitter().addObserver(nbTrans2_Or.getBase());

		NBaseTransistor nbTrans3_Or = new NBaseTransistor();
		bat.addObserver(nbTrans3_Or.getCollector());
		nbTrans2_Or.getEmitter().addObserver(nbTrans3_Or.getBase());

		nbTrans3_Or.getEmitter().addObserver(output);
	}

	public boolean getOutput() {
		return output.getValue();
	}

	public static void main(String... args) {
		Xor xor = new Xor(new GateInput(true), new GateInput(true), 0);
		System.out.println(xor.getOutput());
	}
}
